﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;

namespace Sunlight.Dispatch.Tools {
    public abstract class DbHelper {
        public static DbHelper GetDbHelp(string connectionStr) {
            if(string.IsNullOrEmpty(connectionStr))
                throw new ArgumentNullException(connectionStr);
            return new SqlServerDbHelper(connectionStr);
        }

        /// <summary>
        /// 参数表示符
        /// </summary>
        public string ParamMark {
            get;
            protected set;
        }

        /// <summary>
        /// 当前数据库当前时间的函数
        /// </summary>
        public string Now {
            get;
            protected set;
        }

        /// <summary>
        /// 分批查询数据，每次查询量
        /// </summary>
        public const int PAGE_SIZE = 500;

        public abstract DbConnection CreateDbConnection();

        public abstract DbCommand CreateDbCommand(string commandText, DbConnection conn, DbTransaction ts);

        public abstract DbParameter CreateDbParameter(string parameterName, object value);

        /// <summary>
        /// 获取Insert操作语句（使用参数方式）
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="keyName">主键字段</param>
        /// <param name="fieldName">其他待新增字段</param>
        /// <returns></returns>
        public abstract string GetInsertSql(string tableName, string keyName, string[] fieldName);

        /// <summary>
        /// 获取Update操作语句（使用参数方式）
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="modifyFields">待修改字段</param>
        /// <param name="conditionFields">条件字段（连接符and、比较符等于）</param>
        /// <returns></returns>
        public abstract string GetUpdateSql(string tableName, string[] modifyFields, string[] conditionFields);

        /// <summary>
        /// 执行insert操作
        /// </summary>
        /// <param name="command">待执行DbCommond</param>
        /// <param name="keyField">主键字段</param>
        /// <returns>自动生成的主键值</returns>
        public abstract int ExecuteInsert(DbCommand command, string keyField);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <returns>返回DataTable对象</returns>
        public abstract DataTable ExecuteDataTable(string sql);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">查询SQL</param>
        /// <param name="sqlParameters">SQL参数</param>
        /// <returns>返回DataTable对象</returns>
        public abstract DataTable ExecuteDataTable(string sql, SqlParameter[] sqlParameters);

        /// <summary>
        /// 执行大量的数据插入操作
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="dataTable">dataTable数据</param>
        /// <param name="ts">事务对象</param>
        public abstract void ExecuteBulkInsert(string tableName, DataTable dataTable, DbTransaction ts);

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">查询SQL</param>
        /// <returns>返回是否执行成功</returns>
        public abstract bool ExecuteTransaction(string sql);

        /// <summary>
        /// 执行大量的数据插入操作
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <param name="dataTable">dataTable数据</param>
        public abstract void ExecuteBulkInsert(string tableName, DataTable dataTable);

        /// <summary>
        /// 使用in条件查询数据
        /// </summary>
        /// <param name="sql">查询语句</param>
        /// <param name="field">in条件字段</param>
        /// <param name="isStringField">是否为字符类型</param>
        /// <param name="values">in值列表</param>
        /// <param name="action">查询结果单条处理方法，string[]：单条记录值，按sql字段顺序，bool是否需要继续读取下一条数据
        /// </param>
        public abstract void QueryDataWithInOperator(string sql, string field, bool isStringField, string[] values, Func<string[], bool> action);

        /// <summary>
        /// 获取指定表结构
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public abstract DataTable GetTableSchema(string tableName);

        /// <summary>
        /// 获取指定表结构
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="notNullableFields">不允许为空的字段名称（大写）</param>
        /// <param name="fieldLenght">string类型字段长度，字段名称（大写）、长度</param>
        public abstract void GetTableSchema(string tableName, out List<string> notNullableFields, out Dictionary<string, int> fieldLenght);

        /// <summary>
        /// 执行SQL操作，并返回Id
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="ts">事务</param>
        /// <param name="sqlParameters">参数</param>
        /// <returns>Id</returns>
        public abstract long ExecuteId(string sql, DbTransaction ts, SqlParameter[] sqlParameters);

        /// <summary>
        /// 执行SQL操作
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="ts">事务</param>
        /// <param name="sqlParameters">参数</param>
        public abstract void ExecuteNone(string sql, DbTransaction ts, SqlParameter[] sqlParameters);

        /// <summary>
        /// 执行SQL操作
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="ts">事务</param>
        public abstract void ExecuteNoQuerySql(string sql, DbTransaction ts);

        /// <summary>
        /// 执行SQL操作
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="ts">事务</param>
        /// <returns>DataTable对象</returns>
        public abstract DataTable ExecuteDataTable(string sql, DbTransaction ts);

        /// <summary>
        /// 执行SQL操作
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="sqlParameters">SQL参数</param>
        public abstract void ExecuteNone(string sql, SqlParameter[] sqlParameters);

        /// <summary>
        /// 获取数据库当前时间
        /// </summary>
        /// <returns></returns>
        public abstract DateTime GetDbTime();
    }
}